package com.zack.util.collections;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import com.zack.util.collections.tuple.Tuple;

public class ListProcessing {

    public static void main(String[] args) {

        ArrayList<Integer> abc = addIntToList(null, 10, 12);
        for (int i = 0; i < abc.size(); i++) {
            System.out.println(abc.get(i));
        }
    }

    
    /**
     * 找到在Alist里（比较前numOnlyContains 个条目），而不在Blist里面的， 封装到一个listX中， 作为tuple的first，
     * 找到在Blist(比较前numOnlyContains 个条目)，而不在Alist里的封装到listY，作为tuple的second， 返回tuple 找到a与blist里面的互斥集
     * 并忽略空格造成的影响。
     * 
     * @param aList
     * @param bList
     * @param numOnlyContains: 只比较前numOnlyContains 个条目
     * @return
     * 效率低的实现， 只适合离线使用。
     */
    public static Tuple excludeLists(List<String> aListOrigin, List<String> bListOrigin, int numOnlyContains) {
        if (numOnlyContains < 0 || numOnlyContains>(aListOrigin.size()<bListOrigin.size()?aListOrigin.size():bListOrigin.size())) {
            numOnlyContains = (aListOrigin.size()<bListOrigin.size()?aListOrigin.size():bListOrigin.size());
        }
        List<String> aList = new ArrayList<>(aListOrigin.subList(0, numOnlyContains));
        List<String> bList = new ArrayList<>(bListOrigin.subList(0, numOnlyContains));
        return excludeLists(aList,bList);
    }
    
    /**
     * 找到在Alist里，而不在Blist里面的， 封装到一个listX中， 作为tuple的first，
     * 找到在Blist，而不在Alist里的封装到listY，作为tuple的second， 返回tuple 找到a与blist里面的互斥集
     * 并忽略空格造成的影响。
     * 
     * @param aList
     * @param bList
     * @return
     * 效率低的实现， 只适合离线使用。
     */
    public static Tuple excludeLists(List<String> aList, List<String> bList) {
        List<String> aSpecList = new ArrayList<>();
        List<String> bSpecList = new ArrayList<>();
        for (String aEle : aList) {
            if (!listContain(aEle, bList)) {
                aSpecList.add(aEle);
            }
        }
        for (String bEle : bList) {
            if (!listContain(bEle, aList)) {
                bSpecList.add(bEle);
            }
        }
        Tuple tuple =  Tuple.<List<String>, List<String>>of(aSpecList, bSpecList);
        return tuple;
    }

    
    /**
     * 分离出a里有但b里没有的， b里有但a里没有的以及，ab共有的，返回的tuple里有3个list。
     * @param aList
     * @param bList
     * @return
     */
    public static Tuple classifyLists(List<String> aList, List<String> bList) {
        List<String> aSpecList = new ArrayList<>();
        List<String> bSpecList = new ArrayList<>();
        List<String> commonList = new ArrayList<>();
        for (String aEle : aList) {
            if (!listContain(aEle, bList)) {
                aSpecList.add(aEle);
            }
        }
        for (String bEle : bList) {
            if (!listContain(bEle, aList)) {
                bSpecList.add(bEle);
            }
        }
        
        List<String> bigList = null;
        bigList = aList.size()>bList.size()?aList:bList;
        final List<String> smallList = aList.size()<bList.size()?aList:bList;
        
        bigList.forEach(e->{
            if (listContain(e, smallList)) {
                commonList.add(e);
            }
        });
        Tuple tuple =  Tuple.<List<String>, List<String>,List<String>>of(aSpecList, bSpecList, commonList);
        return tuple;
    }
    
    /**
     * 判断一个str是否在list并忽略前后空格造成的影响
     * @param x
     * @param strList
     * @return
     */
    public static boolean listContain(String x, List<String> strList) {
        for(String str:strList) {
            if (x.trim().equals(str.trim())) {
                return true;
            }
        }
        return false;
    }
    
    
    /**
     * 倒存字符串----------------------------- 接受一个集合返回一个倒着存的数组。 例如 a,b,c,d 返回 d,c,b,a
     * 
     * @param list
     * @return 倒存集合
     */
    public static ArrayList<String> reverseList(ArrayList<String> list) {
        ArrayList<String> newList = new ArrayList<String>();
        for (int i = list.size() - 1; i >= 0; i--) {
            newList.add(list.get(i));
        }
        return newList;
    }

    /**
     * 判断多个list包含的东西是否一样
     */
    public static boolean equalListString(ArrayList<String>... arrayLists) {
        // 首先判断集合长度是否一样
        int length = arrayLists[0].size();
        for (ArrayList<String> list : arrayLists) {
            if (list.size() != length) {
                return false;
            }
        }
        for (int k = 0; k < length; k++) {
            String current = arrayLists[0].get(k);
            for (ArrayList<String> temp : arrayLists) {
                if (!temp.get(k).equals(current)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 给一个list进行内容去重。 然后返回去重后的list。
     * 
     * @param strList
     */
    public static List<String> reduceDuplicateFromList(List<String> strList) {
        Set<String> set = new HashSet<>(strList);
        strList = new ArrayList<>(set);
        return strList;
    }

    /**
     * 快速生成带有数据的list---int型号 这个方法是用来快速往list里面加入一堆数字。 例如addIntToList(null,10,12);
     * 10表示从0到10全部加入到list中去， 第二个数以后的是就是表示单独加这个数。 此处addIntToList(null,10,12) 结果是 0 1
     * 2 3 4 5 6 7 8 9 12 这些数加入到list中去。 addIntToList(null,10,-65535) 表示只把0-10
     * 加入list中。 如果是addIntToList(0,2,3,4,7,89) 表示只把2,3,4,7,89 加入到list中去
     * 其中null表示你要往哪个list里面添加， 如果是null表示新建一个集合， 否则就是往给定的集合里面添加
     * 
     * @param length1
     * @param lotsNum
     * @return
     */
    public static ArrayList<Integer> addIntToList(ArrayList<Integer> intList, int length1, int... lotsNum) {
        ArrayList<Integer> list;
        if (intList == null) {
            list = new ArrayList<>();
        } else {
            list = intList;
        }

        if (length1 != 0) {
            for (int i = 0; i < length1; i++) {
                list.add(i);
            }
        }
        if (lotsNum != null && lotsNum[0] != -65535) {
            for (int x : lotsNum) {
                list.add(x);
            }
        }

        return list;
    }

    /**
     * 快速生成带有数据的list---double型号 这个方法是用来快速往list里面加入一堆数字。
     * 例如addDoubleToList(null,10,12); 10表示从0到10全部加入到list中去， 第二个数以后的是就是表示单独加这个数。
     * 此处addDoubleToList(null,10,12) 结果是 0 1 2 3 4 5 6 7 8 9 12 这些数加入到list中去。
     * addIntToList(null,10,-65535) 表示只把0-10 加入list中。
     * 如果是addDoubleToList(0,2,3,4,7,89) 表示只把2,3,4,7,89 加入到list中去
     * 其中null表示你要往哪个list里面添加， 如果是null表示新建一个集合， 否则就是往给定的集合里面添加
     * 
     * @param intList
     * @param length1
     * @param lotsNum
     * @return
     */
    public static ArrayList<Double> addDoubleToList(ArrayList<Double> intList, int length1, Double... lotsNum) {
        ArrayList<Double> list;
        if (intList == null) {
            list = new ArrayList<>();
        } else {
            list = intList;
        }

        if (length1 != 0) {
            for (int i = 0; i < length1; i++) {
                list.add(i * 1.0);
            }
        }
        if (lotsNum != null && lotsNum[0] != -65535) {
            for (Double x : lotsNum) {
                list.add(x);
            }
        }

        return list;
    }

}
